home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / NR4.C < prev    next >
C/C++ Source or Header  |  1997-01-19  |  24KB  |  829 lines

  1. /* net/rom level 4 (transport) protocol implementation
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  * Ported to NOS by SM0RGV, 890525.
  5.  * Inactivity timeout by WG7J, 920325
  6.  */
  7.  
  8. #include "global.h"
  9. #ifdef NETROM
  10. #include "mbuf.h"
  11. #include "timer.h"
  12. #include "ax25.h"
  13. #include "netrom.h"
  14. #include "cmdparse.h"
  15.  
  16. #if !defined(_lint)
  17. static char rcsid[] OPTIONAL = "$Id: nr4.c,v 1.14 1997/01/19 21:13:05 root Exp root $";
  18. #endif
  19.  
  20. #undef NR4DEBUG
  21.  
  22. /* Globals: */
  23.  
  24. /* The circuit table */
  25.  
  26. struct nr4circp *Nr4circuits;
  27.  
  28.  
  29. /* Various limits */
  30.  
  31. unsigned short Nr4window = 4;    /* Max window to negotiate */
  32. unsigned short Nr4retries = 10;    /* Max retries */
  33. unsigned short Nr4qlimit = 2048;/* Max bytes on receive queue */
  34.  
  35. int NR4MAXCIRC = _NR4MAXCIRC;    /* maximum number of open circuits */
  36.  
  37.  
  38. /* Timers */
  39.  
  40. int32 Nr4irtt = 45000L;        /* Initial round trip time */
  41. int32 Nr4acktime = 3000L;    /* ACK delay timer */
  42. int32 Nr4choketime = 180000L;    /* CHOKEd state timeout */
  43.  
  44. static void nr4ackours (struct nr4cb *, unsigned, int);
  45. static void nr4choke (struct nr4cb *);
  46. static void nr4gotnak (struct nr4cb *, unsigned);
  47. static void nr4rframe (struct nr4cb *, unsigned, struct mbuf *);
  48. int donr4tdisc (int argc, char **argv, void *p);
  49.  
  50. #ifdef NR4TDISC
  51.  
  52. static int32 Nr4tdiscinit = 0UL;    /* Inactivity timeout - WG7J */
  53.  
  54.  
  55. int
  56. donr4tdisc (int argc, char **argv, void *p OPTIONAL)
  57. {
  58.     return setlong (&Nr4tdiscinit, "NR4 redundancy timer (sec)", argc, argv);
  59. }
  60.  
  61.  
  62. /* Changes are if we reachs this, with 'normal' values of tdisc,
  63.  * the other end has already timed  and retried out.
  64.  * So simply reset the control block - WG7J
  65.  */
  66.  
  67. #ifdef notdef
  68. /* This doesn't seem to catch ALL cases,
  69.  * if someone can fix this, please let me know - WG7J
  70.  */
  71. void
  72. nr4_redundant (cb)
  73. struct nr4cb *cb;
  74. {
  75. struct nr4hdr hdr;
  76.  
  77.     switch (cb->state) {
  78.         case NR4STCPEND:
  79.         case NR4STCON:
  80.             /* Format disconnect request packet */
  81.             hdr.opcode = NR4OPDISRQ;
  82.             hdr.yourindex = cb->yournum;
  83.             hdr.yourid = cb->yourid;
  84.  
  85.             /* Set and start timer */
  86.             cb->cdtries = 1;
  87.             set_timer (&cb->tcd, 2 * cb->srtt);
  88.             cb->tcd.func = nr4cdtimeout;
  89.             cb->tcd.arg = cb;
  90.             start_timer (&cb->tcd);
  91.  
  92.             /* Send packet */
  93.             nr4sframe (cb->remote.node, &hdr, NULLBUF);
  94.  
  95.             /* Signal state change.  nr4state will take care of stopping */
  96.             /* the appropriate timers and resetting window pointers. */
  97.             nr4state (cb, NR4STDPEND);
  98.             break;
  99.     }
  100.  
  101. }
  102.  
  103. #endif
  104.  
  105. #endif /* NR4TDISC */
  106.  
  107.  
  108.  
  109. /* This function is called when a net/rom layer four frame */
  110. /* is discovered inside a datagram addressed to us */
  111.  
  112. void
  113. nr4input (struct nr4hdr *hdr, struct mbuf *bp)
  114. {
  115. struct nr4hdr rhdr;
  116. struct nr4cb *cb, *cb2 = NULLNR4CB;
  117. int op;
  118. unsigned window;
  119. int acceptc;        /* indicates that connection should be accepted */
  120. int newconn;        /* indicates that this is a new incoming connection.  You'll see. */
  121. int gotchoke;        /* The choke flag was set in this packet */
  122. int i;
  123. long t;
  124.  
  125.     op = hdr->opcode & NR4OPCODE;    /* Mask off flags */
  126.  
  127.     if (op == NR4OPCONRQ) {    /* process connect request first */
  128.         acceptc = 1;
  129.         newconn = 0;
  130.  
  131.         /* These fields are sent regardless of success */
  132.         rhdr.yourindex = hdr->u.conreq.myindex;
  133.         rhdr.yourid = hdr->u.conreq.myid;
  134.  
  135.         /* Check to see if we have already received a connect */
  136.         /* request for this circuit. */
  137.         if ((cb = match_n4circ (hdr->u.conreq.myindex,
  138.         hdr->u.conreq.myid, hdr->u.conreq.user, hdr->u.conreq.node))
  139.             == NULLNR4CB) {    /* No existing circuit if NULL */
  140.  
  141.             /* If low on memory, don't accept - WG7J */
  142.             /* Try to get a new circuit */
  143.             if ((cb = new_n4circ ()) == NULLNR4CB)
  144.                 acceptc = 0;
  145.             else {
  146.                 /* See if we have any listening sockets */
  147.                 for (i = 0; i < NR4MAXCIRC; i++) {
  148.                     if ((cb2 = Nr4circuits[i].ccb) == NULLNR4CB)
  149.                         continue;    /* not an open circuit */
  150.                     if (cb2->state == NR4STLISTEN)
  151.                         /* A listener was found */
  152.                         break;
  153.                 }
  154.                 if (i == NR4MAXCIRC) {    /* We are refusing connects */
  155.                     acceptc = 0;
  156.                     free_n4circ (cb);
  157.                 }
  158.                 if (cb2 && acceptc) {
  159.                     /* Load the listeners settings */
  160.                     cb->clone = cb2->clone;
  161.                     cb->user = cb2->user;
  162.                     cb->t_upcall = cb2->t_upcall;
  163.                     cb->s_upcall = cb2->s_upcall;
  164.                     cb->r_upcall = cb2->r_upcall;
  165.                     ASSIGN (cb->local, cb2->local);
  166.  
  167.                     /* Window is set to min of the offered
  168.                      * and local windows */
  169.                     window = hdr->u.conreq.window > Nr4window ?
  170.                         Nr4window : hdr->u.conreq.window;
  171.  
  172.                     if (init_nr4window (cb, window) == -1) {
  173.                         free_n4circ (cb);
  174.                         acceptc = 0;
  175.                     } else {
  176.                         /* Set up control block */
  177.                         cb->yournum = hdr->u.conreq.myindex;
  178.                         cb->yourid = hdr->u.conreq.myid;
  179.                         memcpy (cb->remote.user, hdr->u.conreq.user, AXALEN);
  180.                         memcpy (cb->remote.node, hdr->u.conreq.node, AXALEN);
  181.                         /* Default round trip time */
  182.                         cb->srtt = Nr4irtt;
  183.                         /* set up timers, window pointers */
  184.                         nr4defaults (cb);
  185.                         cb->state = NR4STDISC;
  186.                         newconn = 1;
  187.                     }    /* End if window successfully allocated */
  188.                 }    /* End if new circuit available */
  189.             }    /* End of memory-low else */
  190.         }        /* End if no existing circuit matching parameters */
  191.         /* Now set up response */
  192.         if (!acceptc) {
  193.             rhdr.opcode = NR4OPCONAK | NR4CHOKE;    /* choke means reject */
  194.             rhdr.u.conack.myindex = 0;
  195.             rhdr.u.conack.myid = 0;
  196.             rhdr.u.conack.window = 0;
  197.         } else if (cb) {
  198.             rhdr.opcode = NR4OPCONAK;
  199.             rhdr.u.conack.myindex = uchar(cb->mynum);
  200.             rhdr.u.conack.myid = uchar(cb->myid);
  201.             rhdr.u.conack.window = uchar(cb->window);
  202.         }
  203.         nr4sframe (hdr->u.conreq.node, &rhdr, NULLBUF);
  204.  
  205.         /* Why, you ask, do we wait until now for the state change
  206.          * upcall?  Well, it's like this:  if the state change triggers
  207.          * something like the mailbox to send its banner, the banner
  208.          * would have gone out *before* the conn ack if we'd done this
  209.          * in the code above.  This is what happens when you don't plan
  210.          * too well.  Learn from my mistakes :-)
  211.          */
  212.         if (newconn)
  213.             nr4state (cb, NR4STCON);    /* connected (no 3-way handshake) */
  214.  
  215.         free_p (bp);
  216.         return;
  217.     }            /* end connect request code */
  218.     /* validate circuit number */
  219.     if ((cb = get_n4circ (hdr->yourindex, hdr->yourid)) == NULLNR4CB) {
  220.         free_p (bp);
  221.         return;
  222.     }
  223.     /* Check for choke flag */
  224.     if (hdr->opcode & NR4CHOKE)
  225.         gotchoke = 1;
  226.     else
  227.         gotchoke = 0;
  228.  
  229.     /* Here's where the interesting stuff gets done */
  230.     switch (cb->state) {
  231.         case NR4STCPEND:
  232.             switch (op) {
  233.                 case NR4OPCONAK:
  234.                     /* Save the round trip time for later use */
  235.                     t = dur_timer (&cb->tcd) - read_timer (&cb->tcd);
  236.                     stop_timer (&cb->tcd);
  237.                     if (gotchoke) {    /* connect rejected */
  238.                         cb->dreason = NR4RREFUSED;
  239.                         nr4state (cb, NR4STDISC);
  240.                         break;
  241.                     }
  242.                     cb->yournum = hdr->u.conack.myindex;
  243.                     cb->yourid = hdr->u.conack.myid;
  244.                     window = hdr->u.conack.window > Nr4window ?
  245.                         Nr4window : hdr->u.conack.window;
  246.  
  247.                     if (init_nr4window (cb, window) == -1) {
  248.                         cb->dreason = NR4RRESET;
  249.                         nr4state (cb, NR4STDISC);
  250.                     } else {
  251.                         nr4defaults (cb);    /* set up timers, window pointers */
  252.  
  253.                         if (cb->cdtries == 1)    /* No retries */
  254.                             /* Use measured rtt */
  255.                             cb->srtt = t;
  256.                         else
  257.                             /* else use default */
  258.                             cb->srtt = Nr4irtt;
  259.  
  260.                         nr4state (cb, NR4STCON);
  261.                         (void) nr4output (cb);    /* start sending anything on the txq */
  262.                     }
  263.                     break;
  264.                 default:
  265.                     /* We can't respond to anything else without
  266.                      * Their ID and index */
  267.                     free_p (bp);
  268.                     return;
  269.             }
  270.             break;
  271.         case NR4STCON:
  272.             switch (op) {
  273.                 case NR4OPDISRQ:
  274.                     /* format reply packet */
  275.                     rhdr.opcode = NR4OPDISAK;
  276.                     rhdr.yourindex = uchar(cb->yournum);
  277.                     rhdr.yourid = uchar(cb->yourid);
  278.                     nr4sframe (cb->remote.node, &rhdr, NULLBUF);
  279.                     cb->dreason = NR4RREMOTE;
  280.                     nr4state (cb, NR4STDISC);
  281.                     break;
  282.                 case NR4OPINFO:
  283.                     /* Do receive frame processing */
  284.                     nr4rframe (cb, (unsigned) hdr->u.info.txseq, bp);
  285.  
  286.                     /* Reset the choke flag if no longer choked.  Processing
  287.                      * the ACK will kick things off again. */
  288.                     if (cb->choked && !gotchoke) {
  289.                         stop_timer (&cb->tchoke);
  290.                         cb->choked = 0;
  291.                     }
  292.                     /* We delay processing the receive sequence number until
  293.                      * now, because the ACK might pull more off the txq and send
  294.                      * it, and we want the implied ACK in those frames to be right
  295.                      *
  296.                      * Only process NAKs if the choke flag is off.  It appears
  297.                      * that NAKs should never be sent with choke on, by the way,
  298.                      * but you never know, considering that there is no official
  299.                      * standard for this protocol
  300.                      */
  301.                     if (hdr->opcode & NR4NAK && !gotchoke)
  302.                         nr4gotnak (cb, (unsigned) hdr->u.info.rxseq);
  303.  
  304.                     /* We always do ACK processing, too, since the NAK of one
  305.                      * packet may be the implied ACK of another.  The gotchoke
  306.                      * flag is used to prevent sending any new frames, since
  307.                      * we are just going to purge them next anyway if this is
  308.                      * the first time we've seen the choke flag.  If we are
  309.                      * already choked, this call will return immediately.
  310.                      */
  311.                     nr4ackours (cb, (unsigned) hdr->u.info.rxseq, gotchoke);
  312.  
  313.                     /* If we haven't seen the choke flag before, purge the
  314.                      * send window and set the timer and the flag.
  315.                      */
  316.                     if (!cb->choked && gotchoke)
  317.                         nr4choke (cb);
  318.                     break;
  319.                 case NR4OPACK:
  320.                     if (cb->choked && !gotchoke) {
  321.                         /* clear choke if appropriate */
  322.                         stop_timer (&cb->tchoke);
  323.                         cb->choked = 0;
  324.                     }
  325.                     if (hdr->opcode & NR4NAK && !gotchoke)
  326.                         nr4gotnak (cb, (unsigned) hdr->u.ack.rxseq);    /* process NAKs */
  327.  
  328.                     nr4ackours (cb, (unsigned) hdr->u.ack.rxseq, gotchoke);    /* and ACKs */
  329.  
  330.                     if (!cb->choked && gotchoke)    /* First choke seen */
  331.                         nr4choke (cb);    /* Set choke status */
  332.  
  333.                     break;
  334.                 default:
  335.                     break;
  336.             }
  337.             break;
  338.         case NR4STDPEND:
  339.             switch (op) {
  340.                 case NR4OPDISAK:
  341.                     cb->dreason = NR4RNORMAL;
  342.                     nr4state (cb, NR4STDISC);
  343.                     break;
  344.                 case NR4OPINFO:
  345.                     /* We can still do receive frame processing until
  346.                      * the disconnect acknowledge arrives, but we won't
  347.                      * bother to process ACKs, since we've flushed our
  348.                      * transmit buffers and queue already.
  349.                      */
  350.                     nr4rframe (cb, (unsigned) hdr->u.info.txseq, bp);
  351.                     break;
  352.                 default:
  353.                     break;
  354.             }
  355.             break;
  356.         default:
  357.             break;
  358.     }            /* End switch(state) */
  359. }
  360.  
  361.  
  362. /* Send a net/rom layer 4 frame.  bp should be NULLBUF unless the frame
  363.  * type is info.
  364.  */
  365. void
  366. nr4sframe (char *dest, struct nr4hdr *hdr, struct mbuf *bp)
  367. {
  368. struct mbuf *n4b;
  369.  
  370.     if ((n4b = htonnr4 (hdr)) == NULLBUF) {
  371.         free_p (bp);
  372.         return;
  373.     } else {
  374.         append (&n4b, bp);
  375.         nr3output (dest, n4b);
  376.     }
  377. }
  378.  
  379.  
  380. /* Receive frame processing */
  381. static void
  382. nr4rframe (struct nr4cb *cb, unsigned rxseq, struct mbuf *bp)
  383. {
  384. struct nr4hdr rhdr;
  385. unsigned window = cb->window;
  386. unsigned rxbuf = rxseq % window;
  387. unsigned newdata = 0;    /* whether to upcall */
  388.  
  389. #ifdef NR4DEBUG
  390.     printf ("Processing received info\n");
  391. #endif
  392.  
  393. #ifdef NR4TDISC
  394.     /* We received data, reset the inactivity timer - WG7J */
  395.     start_timer (&cb->tdisc);
  396. #endif
  397.  
  398.     /* If we're choked, just reset the ACK timer to blast out
  399.      * another CHOKE indication after the ackdelay
  400.      */
  401.     if (cb->qfull) {
  402.         start_timer (&cb->tack);
  403.         return;
  404.     }
  405.     /* If frame is out of sequence, it is either due to a lost frame
  406.      * or a retransmission of one seen earlier.  We do not want to NAK
  407.      * the latter, as the far end would see this as a requirement to
  408.      * retransmit the expected frame, which is probably already in the
  409.      * pipeline.  This in turn would cause another out-of-sequence
  410.      * condition, another NAK, and the process would repeat indefinitely.
  411.      * Therefore, if the frame is out-of-sequence, but within the last
  412.      * 'n' frames by sequence number ('n' being the window size), just
  413.      * accept it and discard it.  Else, NAK it if we haven't already.
  414.      *      (Modified by Rob Stampfli, kd8wk, 9 Jan 1990)
  415.      */
  416.     if (rxseq != cb->rxpected && !cb->naksent) {
  417. #ifdef NR4DEBUG
  418.         printf ("Frame out of sequence -- expected %u, got %u.\n",
  419.             cb->rxpected, rxseq);
  420. #endif
  421.         if (nr4between ((unsigned) cb->rxpected,
  422.            (rxseq + window) & NR4SEQMASK, (unsigned) cb->rxpastwin))
  423.             /* just a repeat of old frame -- queue ack for
  424.              * expected frame
  425.              */
  426.             start_timer (&cb->tack);
  427.         else {        /* really bogus -- a NAKable frame */
  428.             rhdr.opcode = NR4OPACK | NR4NAK;
  429.             rhdr.yourindex = uchar(cb->yournum);
  430.             rhdr.yourid = uchar(cb->yourid);
  431.             rhdr.u.ack.rxseq = cb->rxpected;
  432.             nr4sframe (cb->remote.node, &rhdr, NULLBUF);
  433.  
  434.             /* Now make sure we don't send any more of these until
  435.              * we see some good data.  Otherwise full window
  436.              * retransmissions would result in a flurry of NAKs
  437.              */
  438.  
  439.             cb->naksent = 1;
  440.         }
  441.     }
  442.     /* If this is a new frame, within the window, buffer it,
  443.      * then see what we can deliver
  444.      */
  445.     if (nr4between ((unsigned) cb->rxpected, rxseq, (unsigned) cb->rxpastwin)
  446.         && !cb->rxbufs[rxbuf].occupied) {
  447. #ifdef NR4DEBUG
  448.         printf ("Frame within window\n");
  449. #endif
  450.         cb->rxbufs[rxbuf].occupied = 1;
  451.         cb->rxbufs[rxbuf].data = bp;
  452.  
  453.         for (rxbuf = cb->rxpected % window; cb->rxbufs[rxbuf].occupied;
  454.              rxbuf = cb->rxpected % window) {
  455. #ifdef NR4DEBUG
  456.             printf ("Removing frame from buffer %d\n", rxbuf);
  457. #endif
  458.             newdata = 1;
  459.             cb->rxbufs[rxbuf].occupied = 0;
  460.             append (&cb->rxq, cb->rxbufs[rxbuf].data);
  461.             cb->rxbufs[rxbuf].data = NULLBUF;
  462.             cb->rxpected = (cb->rxpected + 1) & NR4SEQMASK;
  463.             cb->rxpastwin = (cb->rxpastwin + 1) & NR4SEQMASK;
  464.         }
  465.         if (newdata) {
  466.             cb->naksent = 0;    /* OK to send NAKs again */
  467.             if (cb->r_upcall != NULLVFP ((struct nr4cb *, int16)))
  468.                 (*cb->r_upcall) (cb, len_p (cb->rxq));
  469.  
  470.             /* Now that our upcall has had a shot at the queue, */
  471.             /* see if it's past the queue length limit.  If so, */
  472.             /* go into choked mode (i.e. flow controlled). */
  473.  
  474.             if (len_p (cb->rxq) > Nr4qlimit) {
  475.                 cb->qfull = 1;
  476.                 nr4ackit ((void *) cb);    /* Tell `em right away */
  477.             } else
  478.                 start_timer (&cb->tack);
  479.         }
  480.     } else            /* It's out of the window or we've seen it already */
  481.         free_p (bp);
  482. }
  483.  
  484.  
  485. /* Send the transmit buffer whose sequence number is seq */
  486. void
  487. nr4sbuf (struct nr4cb *cb, unsigned seq)
  488. {
  489. struct nr4hdr hdr;
  490. struct mbuf *bufbp, *bp;
  491. unsigned bufnum = seq % cb->window;
  492. struct timer *t;
  493.  
  494.     /* sanity check */
  495.     if (bufnum >= cb->window) {
  496. #ifdef NRDEBUG
  497.         printf ("sbuf: buffer number %u beyond window\n", bufnum);
  498. #endif
  499.         return;
  500.     }
  501.     /* Stop the ACK timer, since our sending of the frame is
  502.      * an implied ACK.
  503.      */
  504.     stop_timer (&cb->tack);
  505.  
  506.     /* Duplicate the mbuf, since we have to keep it around
  507.      * until it is acknowledged
  508.      */
  509.     bufbp = cb->txbufs[bufnum].data;
  510.  
  511.     /* Notice that we use copy_p instead of dup_p.  This is because
  512.      * a frame can still be sitting on the AX.25 send queue when it
  513.      * get acknowledged, and we don't want to deallocate its data
  514.      * before it gets sent!
  515.      */
  516.     if ((bp = copy_p (bufbp, len_p (bufbp))) == NULLBUF) {
  517.         (void) free_mbuf (bp);
  518.         return;
  519.     }
  520.     /* Prepare the header */
  521.     if (cb->qfull)        /* are we choked? */
  522.         hdr.opcode = NR4OPINFO | NR4CHOKE;
  523.     else
  524.         hdr.opcode = NR4OPINFO;
  525.     hdr.yourindex = uchar(cb->yournum);
  526.     hdr.yourid = uchar(cb->yourid);
  527.     hdr.u.info.txseq = (unsigned char) (seq & NR4SEQMASK);
  528.     hdr.u.info.rxseq = cb->rxpected;
  529.  
  530.     /* Send the frame, then set and start the timer */
  531.     nr4sframe (cb->remote.node, &hdr, bp);
  532.  
  533.     t = &cb->txbufs[bufnum].tretry;
  534.     set_timer (t, (1 << cb->blevel) * (4 * cb->mdev + cb->srtt));
  535.     start_timer (t);
  536. }
  537.  
  538.  
  539. /* Check to see if any of our frames have been ACKed */
  540.  
  541. static void
  542. nr4ackours (cb, seq, gotchoke)
  543. struct nr4cb *cb;
  544. unsigned seq;
  545. int gotchoke;            /* The choke flag is set in the received frame */
  546. {
  547. unsigned txbuf;
  548. struct timer *t;
  549.  
  550.     /* If we are choked, there is nothing in the send window
  551.      * by definition, so we can just return.
  552.      */
  553.     if (cb->choked)
  554.         return;
  555.  
  556.     /* Adjust seq to point to the frame being ACK'd, not the one
  557.      * beyond it, which is how it arrives.
  558.      */
  559.     seq = (seq - 1) & NR4SEQMASK;
  560.  
  561.     /* Free up all the ack'd frames, and adjust the round trip
  562.      * timing stuff
  563.      */
  564.     while (nr4between ((unsigned) cb->ackxpected, seq, (unsigned) cb->nextosend)) {
  565. #ifdef NR4DEBUG
  566.         printf ("Sequence # %u acknowledged\n", seq);
  567. #endif
  568.         cb->nbuffered--;
  569.         txbuf = cb->ackxpected % cb->window;
  570.         (void) free_mbuf (cb->txbufs[txbuf].data);
  571.         cb->txbufs[txbuf].data = NULLBUF;
  572.         cb->ackxpected = (cb->ackxpected + 1) & NR4SEQMASK;
  573.  
  574.         /* Round trip time estimation, cribbed from TCP */
  575.         if (cb->txbufs[txbuf].retries == 0) {
  576.             /* We only sent this one once */
  577.             int32 rtt;
  578.             int32 abserr;
  579.  
  580.             t = &cb->txbufs[txbuf].tretry;
  581.             /* get our rtt in msec */
  582.             rtt = dur_timer (t) - read_timer (t);
  583.             abserr = (rtt > cb->srtt) ? rtt - cb->srtt : cb->srtt - rtt;
  584.             cb->srtt = (cb->srtt * 7 + rtt) >> 3;        /*lint !e704 */
  585.             cb->mdev = (cb->mdev * 3 + abserr) >> 2;    /*lint !e704 */
  586.  
  587.             /* Reset the backoff level */
  588.             cb->blevel = 0;
  589.         }
  590.         stop_timer (&cb->txbufs[txbuf].tretry);
  591.     }
  592.     /* Now we recalculate tmax, the maximum number of retries for
  593.      * any frame in the window.  tmax is used as a baseline to
  594.      * determine when the window has reached a new high in retries.
  595.      * We don't want to increment blevel for every frame that times
  596.      * out, since that would lead to us backing off too fast when
  597.      * all the frame timers expired at around the same time.
  598.      */
  599.     cb->txmax = 0;
  600.  
  601.     for (seq = cb->ackxpected;
  602.          nr4between ((unsigned) cb->ackxpected, seq, (unsigned) cb->nextosend);
  603.          seq = (seq + 1) & NR4SEQMASK)
  604.         if (cb->txbufs[seq % cb->window].retries > cb->txmax)
  605.             cb->txmax = cb->txbufs[seq % cb->window].retries;
  606.  
  607.     /* This is kind of a hack.  This function is called under
  608.      * three different conditions:  either we are choked, in
  609.      * which case we return immediately, or we are not choked,
  610.      * in which case we proceed normally to keep the send
  611.      * window full, or we have seen the choke flag for the first
  612.      * time.  In the last case, gotchoke is true while cb->choked
  613.      * is false.  We want to process any acknowledgments of existing
  614.      * frames in the send window before we purge it, while at the
  615.      * same time we don't want to take anything else off the txq
  616.      * or send it out.  So, in the third case we listed, we return
  617.      * now since we've processed the ACK.
  618.      */
  619.  
  620.     if (gotchoke)
  621.         return;
  622.  
  623.     (void) nr4output (cb);        /* yank stuff off txq and send it */
  624.  
  625.     /* At this point, either the send window is full, or
  626.      * nr4output() didn't find enough on the txq to fill it.
  627.      * If the window is not full, then the txq must be empty,
  628.      * and we'll make a tx upcall
  629.      */
  630.     if (cb->nbuffered < cb->window && cb->t_upcall != NULLVFP ((struct nr4cb *, int16)))
  631.         (*cb->t_upcall) (cb, (int16) ((cb->window - cb->nbuffered) * NR4MAXINFO));
  632.  
  633. }
  634.  
  635.  
  636. /* If the send window is open and there are frames on the txq,
  637.  * move as many as possible to the transmit buffers and send them.
  638.  * Return the number of frames sent.
  639.  */
  640. int
  641. nr4output (struct nr4cb *cb)
  642. {
  643. int numq, i;
  644. struct mbuf *bp;
  645. struct nr4txbuf *tp;
  646.  
  647.     /* Are we in the proper state? */
  648.     if (cb->state != NR4STCON || cb->choked)
  649.         return 0;    /* No sending if not connected */
  650.     /* or if choked */
  651.  
  652.     /* See if the window is open */
  653.     if (cb->nbuffered >= cb->window)
  654.         return 0;
  655.  
  656.     numq = len_q (cb->txq);
  657.  
  658. #ifdef NR4DEBUG
  659.     printf ("nr4output: %d packets on txq\n", numq);
  660. #endif
  661.  
  662.     for (i = 0; i < numq; i++) {
  663.         bp = dequeue (&cb->txq);
  664. #ifdef NR4DEBUG
  665.         if (len_p (bp) > NR4MAXINFO) {    /* should be checked higher up */
  666.             printf ("Upper layers queued too big a buffer\n");
  667.             continue;
  668.         }
  669. #endif
  670.         /* Set up and send buffer */
  671.         tp = &cb->txbufs[cb->nextosend % cb->window];
  672.         tp->retries = 0;
  673.         tp->data = bp;
  674.         nr4sbuf (cb, (unsigned) cb->nextosend);
  675.  
  676.         /* Update window and buffered count */
  677.         cb->nextosend = (cb->nextosend + 1) & NR4SEQMASK;
  678.         if (++cb->nbuffered >= cb->window)
  679.             break;
  680.     }
  681.     return i;
  682. }
  683.  
  684.  
  685. void
  686. nr4state (struct nr4cb *cb, int newstate)
  687. {
  688. int i;
  689. int oldstate = cb->state;
  690.  
  691.     cb->state = newstate;
  692.  
  693.     switch (cb->state) {
  694. #ifdef NR4TDISC
  695.         case NR4STCON:
  696.             /* We're connected now, start inactivity timer - WG7J */
  697.             set_timer (&cb->tdisc, Nr4tdiscinit * 1000L);
  698.             /* cb->tdisc.func = nr4_redundant ;
  699.              * Second try; the call to nr4_redundant() (see above)
  700.              * doesn't seem to catch ALL situations.
  701.              * Changes are if we reachs this, with 'normal' values of tdisc,
  702.              * the other end has already timed out and retried out.
  703.              * So simply reset the control block - WG7J
  704.              */
  705.             cb->tdisc.func = (void (*)(void *)) reset_nr4;
  706.             cb->tdisc.arg = cb;
  707.             start_timer (&cb->tdisc);
  708.             break;
  709. #endif
  710.         case NR4STDPEND:
  711.             stop_timer (&cb->tchoke);
  712. #ifdef NR4TDISC
  713.             start_timer (&cb->tdisc);
  714. #endif
  715.  
  716.             /* When we request a disconnect, we lose the contents of
  717.              * our transmit queue and buffers, but we retain our ability
  718.              * to receive any packets in transit until a disconnect
  719.              * acknowledge arrives
  720.              */
  721.             free_q (&cb->txq);
  722.  
  723.             for (i = 0; (unsigned) i < cb->window; i++) {
  724.                 (void) free_mbuf (cb->txbufs[i].data);
  725.                 cb->txbufs[i].data = NULLBUF;
  726.                 stop_timer (&cb->txbufs[i].tretry);
  727.             }
  728.  
  729.             /* Tidy up stats: roll the top window pointer back
  730.              * and reset nbuffered to reflect this.  Not really
  731.              * necessary, but leads to a bit more truth telling
  732.              * in the status displays.
  733.              */
  734.             cb->nextosend = cb->ackxpected;
  735.             cb->nbuffered = 0;
  736.             break;
  737.         case NR4STDISC:
  738.             stop_timer (&cb->tchoke);
  739.             stop_timer (&cb->tack);
  740.             stop_timer (&cb->tcd);
  741. #ifdef NR4TDISC
  742.             stop_timer (&cb->tdisc);
  743. #endif
  744.  
  745.             /* We don't clear the rxq, since the state change upcall
  746.              * may pull something off of it at the last minute.
  747.              */
  748.             free_q (&cb->txq);
  749.  
  750.             /* The following loop will only be executed if the
  751.              * window was set, since when the control block is
  752.              * calloc'd the window field gets a 0 in it.  This
  753.              * protects us from dereferencing an unallocated
  754.              * window buffer pointer
  755.              */
  756.             for (i = 0; (unsigned) i < cb->window; i++) {
  757.                 (void) free_mbuf (cb->rxbufs[i].data);
  758.                 cb->rxbufs[i].data = NULLBUF;
  759.                 (void) free_mbuf (cb->txbufs[i].data);
  760.                 cb->txbufs[i].data = NULLBUF;
  761.                 stop_timer (&cb->txbufs[i].tretry);
  762.             }
  763.             break;
  764.         default:
  765.             break;
  766.     }
  767.  
  768.     if (oldstate != newstate && cb->s_upcall != NULLVFP ((struct nr4cb *, int, int)))
  769.         (*cb->s_upcall) (cb, oldstate, newstate);
  770.  
  771.     /* We take responsibility for deleting the circuit
  772.      * descriptor.  Don't do this anywhere else!
  773.      */
  774.     if (newstate == NR4STDISC)
  775.         free_n4circ (cb);
  776. }
  777.  
  778.  
  779. /* Process NAKs.  seq indicates the next frame expected by the
  780.  * NAK'ing station.
  781.  */
  782.  
  783. static void
  784. nr4gotnak (struct nr4cb *cb, unsigned seq)
  785. {
  786.     if (nr4between ((unsigned) cb->ackxpected, seq, (unsigned) cb->nextosend))
  787.         nr4sbuf (cb, seq);
  788. }
  789.  
  790.  
  791. /* This is called when we first get a CHOKE indication from the
  792.  * remote.  It purges the send window and sets the choke timer.
  793.  */
  794.  
  795. static void
  796. nr4choke (struct nr4cb *cb)
  797. {
  798. unsigned seq;
  799. struct mbuf *q, *bp;
  800. struct nr4txbuf *t;
  801.  
  802.     q = cb->txq;
  803.  
  804.     /* We purge the send window, returning the buffers to the
  805.      * txq in the proper order.
  806.      */
  807.     for (seq = (cb->nextosend - 1) & NR4SEQMASK;
  808.          nr4between ((unsigned) cb->ackxpected, seq, (unsigned) cb->nextosend);
  809.          seq = (seq - 1) & NR4SEQMASK) {
  810.  
  811.         t = &cb->txbufs[seq % cb->window];
  812.         stop_timer (&t->tretry);
  813.         bp = t->data;
  814.         t->data = NULLBUF;
  815.         enqueue (&bp, q);    /* prepend this packet to the queue */
  816.         q = bp;
  817.     }
  818.  
  819.     cb->nextosend = cb->ackxpected;    /* close the window */
  820.     cb->nbuffered = 0;    /* nothing in the window */
  821.     cb->txq = q;        /* Replace the txq with the one that has */
  822.     /* the purged packets prepended */
  823.     cb->choked = 1;        /* Set the choked flag */
  824.  
  825.     start_timer (&cb->tchoke);
  826. }
  827.  
  828. #endif /* NETROM */
  829.